package com.choudou5.solr.utils;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.choudou5.solr.bean.sys.SysExceptionBean;
import com.choudou5.solr.framework.holder.SysContextHolder;
import com.choudou5.solr.service.ServiceHelper;
import com.choudou5.solr.service.sys.SysExceptionService;
import com.choudou5.solr.util.*;
import com.choudou5.solr.util.exception.BizException;
import com.choudou5.solr.util.thread.ThreadUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * @name：SysExceptionUtil 说明
 * @author：xuhaowen
 * @date：2018-08-25
 */
public class SysExceptionUtil {

    protected static final Logger logger = LoggerFactory.getLogger(SysExceptionUtil.class);

    private static SysExceptionService exceptionService = ServiceHelper.singleton(SysExceptionService.class);

    private static Queue<SysExceptionBean> queue = new ArrayBlockingQueue(500);
    private static volatile long lastTimestamp = -1;

    public static void traceError(Throwable e, HttpServletRequest req){
        traceError("sys", e, req);
    }

    public static void traceError(String module, Throwable e, HttpServletRequest req){
        //异常栈信息 gizp压缩
        String stacktrace = GzipUtil.compress(ExceptionUtil.stacktraceToString(e));
        SysExceptionBean bean = new SysExceptionBean();
        bean.setModule(module);
        bean.setBrief(e.getMessage());
        bean.setType(e.getClass().getName());
        bean.setAccessIp(IpUtil.getRealIpAddr(req));
        bean.setException(stacktrace);
        bean.setServer(SysContextHolder.getServiceHost());
        bean.setCreateTime(new Date());
        long timestamp = System.currentTimeMillis();
        queue.add(bean);
        if((timestamp - lastTimestamp) > 3000){
            //批量取出语句
            int index = 0;
            SysExceptionBean exBean = null;
            final List<SysExceptionBean> list = new ArrayList<>();
            while(index < 10 && ((exBean=queue.poll()) != null)){
                list.add(exBean);
                index++;
            }
            //异步保存
            ThreadUtil.execAsync(new Runnable() {
                @Override
                public void run() {
                try {
                    exceptionService.batchAddBean(list);
                } catch (BizException e) {
                    logger.error("批量保存失败", e);
                }
                }
            });
        }
        lastTimestamp = timestamp;
        DingTalkUtil.sendTextMsgToOps("系统有新的异常信息：" + module + " " + bean.getBrief());
    }

}
